package edu.tum.cs.i1.pse;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;

/**
 * Uses the file system as cache. The URL is being URL-encoded before stored as a file.
 * @author arj
 *
 */
public class Cache implements ConnectorInterface {

	public Cache() {
	}
	
	@Override
	public InputStream open(URL url) {
		System.out.println("Getting cached file from filesystem");
		FileInputStream fis = null;
		String fileName = getFilenameFromUrl(url);
		try {
			fis = new FileInputStream(new File(fileName));
		} catch (FileNotFoundException e) {}
		if (fis == null)
			System.err.println("File \"" + fileName + "\" not found!");
		return fis;
	}

	@Override
	public void close(InputStream stream) throws IOException {
		System.out.println("Closing connection");
		stream.close();
	}
	
	/**
	 * Writes the input stream to the file system named in relation to the URL. If the file exists it is overwritten.
	 * @param stream The file stream to save.
	 * @param url The URL is used to determine the file name so the file can be retrieved later.
	 */
	public static void cacheRessource(InputStream stream, URL url) {
		if (stream == null || url == null)
			return;
		
		System.out.println("Caching ressource in file system");
		
		OutputStream output = null;
		try {
			String fileName = getFilenameFromUrl(url);
			File file = new File(fileName);
			if (!file.exists())
				file.createNewFile();

			byte[] buffer = new byte[8 * 1024];
			output = new FileOutputStream(fileName);
		
		    int bytesRead;
		    while ((bytesRead = stream.read(buffer)) != -1) {
		    	output.write(buffer, 0, bytesRead);
		    }
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(-1);
		} catch (IOException ioe) {
			ioe.printStackTrace();
			System.exit(-1);
		} finally {
			if (output != null)
			{
				try {
					output.close();
				} catch (IOException e) {
					// Suppress
				}
			}
		}
	}

	/**
	 * Checks if the file is in the cache already
	 * @param url The URL of the ressource
	 * @return True if the resource is in the cache, otherwise false
	 */
	public static boolean hasRessource(URL url) {
		File f = new File(getFilenameFromUrl(url));
		//return f.exists();
		System.out.println(f.exists() ? "The file exists in cache" : "The file is NOT cached");
		return f.exists();
	}
	
	/**
	 * Converts the URL into a valid file name (using URLencoding)
	 * @param url The URL to turn into a file name
	 * @return The file name
	 */
	private static String getFilenameFromUrl(URL url) {
		try {
			return URLEncoder.encode(url.toExternalForm(), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("The encoding is not supported in this OS.");
		}
	}
	
}
